<script setup>
import { ref, reactive, computed, watch } from 'vue'
import ImageCode from '@/components/image-code/index.vue'
import {useRouter, useRoute} from 'vue-router'
import {randomString} from '@/utils/index.js'
import useUserStore from '@/stores/user.js'
import {ElMessage} from 'element-plus'
import useThemeStore from '@/stores/theme.js'
import { httpBindMobile, httpSendSms, httpGetQrCode, httpBindOpenId, httpGetLoginStatus } from '@/api/user.js'
import { setToken } from '@/utils/auth.js'

const login_type = ref(1)
const second = ref('')
const timer = ref(0)
const loginForm = ref(null)
const bindForm = ref(null)
const show_bind = ref(false)
const qrCode = ref('')
const sceneId = ref('')
const data = reactive({
  username: '',
  password: '',
  img_code: '',
  phone_number: '',
  phone_code: '',
  category: 1,
  open_id: ''
})
const userStore = useUserStore()
const route = useRoute()
const router = useRouter()
const themeStore = useThemeStore()
const loading = ref(false)

let imageErrCount = 0
const imageCodeLength = 4
const imageStr = ref(randomString(imageCodeLength))
const changeImageStr = () => {
  imageStr.value = randomString(imageCodeLength)
}

const usernameErrorMessage = computed(() => {
  return data.category === 1 ? "学号" : "工号"
})

const validateImageStr = (rule, value, callback) => {
  if (value.toLowerCase() !== imageStr.value.toLowerCase()) {
    if (imageErrCount < 3) {
      imageErrCount++
    } else {
      changeImageStr()
      imageErrCount = 0
    }
    return callback(new Error('验证码不正确'))
  }
  return callback()
}

const validateUsername = (rule, value, callback) => {
  if (value.trim() === "") {
    return callback(new Error("请输入" + usernameErrorMessage.value))
  }
  return callback()
}

const verifyMobile = (rule, value, callback) => {
  value = value + ""
  if (!value.startsWith("1") || value.includes("e") || value.includes("E") || value.length !== 11) {
    return callback(new Error("手机号格式不正确"))
  }
  return callback()
}

const rules = {
  username: [{validator: validateUsername, trigger: 'blur'}],
  password: [{required: true, message: '请输入登录密码', trigger: 'blur'}],
  phone_number: [
    {required: true, message: '请输入手机号', trigger: 'blur'},
    {validator: verifyMobile, trigger: 'blur'},
  ],
  img_code: [
    {required: true, message: '请输入图片验证码', trigger: 'blur'},
    {validator: validateImageStr, trigger: 'blur'}
  ]
}

const sendSmsCode = async (formEl) => {
  if (timer.value || second.value) {
    return
  }
  const valid = await formEl.validate(valid => valid)
  if (!valid) return
  loading.value = true
  const res = await httpSendSms({phone_number: data.phone_number})
    .then(() => true)
    .catch(() => false)
  loading.value = false
  if (!res) {
    return
  }
  second.value = 59 + ''
  timer.value = setInterval(() => {
    if (parseInt(second.value) <= 0) {
      second.value = ''
      clearInterval(timer.value)
      timer.value = 0
      return
    }
    second.value = (parseInt(second.value) - 1) + ''
  }, 1000)
}

const validateSmsCode = () => {
  if (!data.phone_code) {
    ElMessage.error('请输入短信验证码')
    return false
  }
  if (data.phone_code.length !== 6 || data.phone_code.includes('e') || data.phone_code.includes('E')) {
    ElMessage.error('短信验证码格式错误')
    return false
  }
  return true
}

const handleLogin = async (formEl) => {
  const valid = await formEl.validate(valid => valid)
  if (!valid) return
  if (login_type.value === 2 && !validateSmsCode()) {
    return
  }
  loading.value = true
  const login_result = await userStore.setLogin({...data, login_type: login_type.value})
  loading.value = false
  if (!login_result) return
  if (login_result === "bind") {
    show_bind.value = true
    return
  }
  goAway()
  ElMessage.success('登录成功')
}

const handleBind = async (formEl) => {
  const valid = await formEl.validate(valid => valid)
  if (!valid) return
  loading.value = true
  let result = null
  if (login_type.value === 2) {
    result = await httpBindMobile({
      category: data.category,
      phone_number: data.phone_number,
      password: data.password,
      job_number: data.username,
    }).catch(() => null)
  } else {
    result = await httpBindOpenId({
      open_id: data.open_id,
      category: data.category,
      password: data.password,
      job_number: data.username,
    }).catch(() => null)
  }
  loading.value = false
  if (result) {
    const {token} = result
    setToken(token)
    userStore.setStrToken(token)
    goAway()
    ElMessage.success("绑定成功")
  }
}


const qr_timer = ref(0)
const result_timer = ref(0)

const refreshQrCode = async () => {
  const response = await httpGetQrCode(data.category).catch(() => null)
  if (!response) return
  const {qrcode, scene_id} = response
  qrCode.value = qrcode
  sceneId.value = scene_id
  if (result_timer.value) {
    clearInterval(result_timer.value)
    result_timer.value = 0
  }
  result_timer.value = setInterval(() => {
    getLoginStatus()
  }, 1000)
}

const getLoginStatus = async () => {
  const response = await httpGetLoginStatus(sceneId.value).catch(() => null)
  if (!response) return
  const {status, token, open_id} = response
  if (status !== 0) {
    clearInterval(result_timer.value)
    clearInterval(qr_timer.value)
  }
  if (status === 1) {
    // 去绑定账号
    show_bind.value = true
    data.open_id = open_id
  } else if (status === 2) {
    // 登录成功
    setToken(token)
    userStore.setStrToken(token)
    goAway()
    ElMessage.success("登录成功")
  }
  // 继续轮训获取结果
}

const goAway = () => {
  const redirect = ref(route.query && route.query.redirect)
  router.push(redirect.value ? redirect.value : '/')
}

const login_type_category = computed(() => {
  return login_type.value + '-' + data.category
})

watch(() => login_type_category.value, (newValue) => {
  if (qr_timer.value) {
    clearInterval(qr_timer.value)
    qr_timer.value = 0
  }
  if (result_timer.value) {
    clearInterval(result_timer.value)
    qr_timer.value = 0
  }
  qrCode.value = ''
  const arr = newValue.split('-')
  if (parseInt(arr[0]) === 3) {
    refreshQrCode()
    qr_timer.value = setInterval(() => {
      refreshQrCode()
    }, 100000)
  }
})

</script>

<template>
  <div class="vw-100 vh-100 login-container flex justify-content-center align-items-center">
<!--    <div @click="themeStore.toggleDark" class="dark-btn">
      <el-switch
          :model-value="themeStore.isDark"
          inline-prompt
          :inactive-value="true"
          :active-value="false"
          active-icon="Sunny"
          inactive-icon="MoonNight"
      />
    </div>-->
    <div class="login-body padding-30" v-if="!show_bind">
      <div class="font-bold font-size-4xl flex justify-content-center line-height-2xl title">
        登录AI大模型应用平台
      </div>
      <div class="font-size-l flex justify-content-center line-height-2xl">
        拥有海量的知识库，你问我答，期待跟您初次相遇
      </div>
      <el-form
          ref="loginForm"
          class="login-form padding-30 margin-top-30 border-radius-xl"
          :rules="rules"
          :label-width="0"
          :model="data"
      >
        <el-form-item class="pw-100">
          <el-radio-group v-model="data.category" class="padding-left-30 font-size">
            <el-radio :value="1" size="large" class="w-100">我是学生</el-radio>
            <el-radio :value="2" size="large" class="w-100">我是老师</el-radio>
          </el-radio-group>
        </el-form-item>
        <el-form-item prop="username" v-if="login_type === 1">
          <el-input
              size="large"
              clearable
              :placeholder="`输入${usernameErrorMessage}`"
              v-model="data.username"
              prefix-icon="User"
              @keyup.native.enter="handleLogin(loginForm)"
          />
        </el-form-item>
        <el-form-item prop="password" v-if="login_type === 1">
          <el-input
              type="password"
              size="large"
              clearable
              :placeholder="`输入登录密码`"
              v-model="data.password"
              prefix-icon="Lock"
              @keyup.native.enter="handleLogin(loginForm)"
          />
        </el-form-item>
        <el-form-item prop="phone_number" v-if="login_type === 2">
          <el-input
              type="number"
              size="large"
              clearable
              :placeholder="`输入手机号`"
              v-model="data.phone_number"
              prefix-icon="Iphone"
              maxlength="11"
              @keyup.native.enter="handleLogin(loginForm)"
          />
        </el-form-item>
        <el-form-item prop="img_code" v-if="login_type !== 3">
          <el-input
              size="large"
              clearable
              placeholder="输入图片验证码"
              v-model="data.img_code"
              prefix-icon="Picture"
              class="pw-60"
              @keyup.native.enter="handleLogin(loginForm)"
          />
          <image-code
              class="margin-left-26 border-radius-xs"
              :identify-code="imageStr"
              @click="changeImageStr"
              :content-width="126"
              :content-height="38"
          />
        </el-form-item>
        <el-form-item prop="phone_code" v-if="login_type === 2">
          <el-input
              type="number"
              size="large"
              clearable
              maxlength="6"
              :placeholder="`手机验证码`"
              v-model="data.phone_code"
              prefix-icon="Message"
              class="pw-60"
              @keyup.native.enter="handleLogin(loginForm)"
          />
          <el-button
            class="margin-left-26"
            :type="second === '' ? 'warning' : 'info'"
            size="large"
            style="width: 124px"
            @click="sendSmsCode(loginForm)"
            v-loading="loading"
          >{{second === '' ? '发送验证码' : second}}</el-button>
        </el-form-item>
        <div class="flex justify-content-center" v-if="login_type === 3">
          <el-image style="width: 300px; height: 300px" :src="qrCode" v-loading="!qrCode"></el-image>
        </div>
        <el-form-item v-if="login_type !== 3">
          <el-button
              size="large"
              type="primary"
              class="pw-100 margin-top-20"
              @click="handleLogin(loginForm)"
              :loading="loading"
          >登 录
          </el-button>
        </el-form-item>
        <div class="flex justify-content-between">
          <el-button text type="primary" v-if="login_type !== 1" @click="login_type = 1">账号密码登录</el-button>
          <el-button text type="primary" v-if="login_type !== 2" @click="login_type = 2">短信验证码登录</el-button>
          <el-button text type="primary" v-if="login_type !== 3" @click="login_type = 3">微信扫码登录</el-button>
        </div>
      </el-form>
      <div class="h-80 pw-100"></div>
    </div>
    <div class="login-body padding-30" v-else>
      <el-form
          ref="bindForm"
          class="login-form padding-30 margin-top-30 border-radius-xl"
          :rules="rules"
          :label-width="0"
          :model="data"
      >
        <div class="font-bold font-size-4xl flex justify-content-center line-height-2xl">
          绑定账号
        </div>
        <el-form-item prop="username">
          <el-input
              size="large"
              clearable
              :placeholder="`输入${usernameErrorMessage}`"
              v-model="data.username"
              prefix-icon="User"
              @keyup.native.enter="handleBind(bindForm)"
          />
        </el-form-item>
        <el-form-item prop="password">
          <el-input
              type="password"
              size="large"
              clearable
              :placeholder="`输入登录密码`"
              v-model="data.password"
              prefix-icon="Lock"
              @keyup.native.enter="handleBind(bindForm)"
          />
        </el-form-item>
        <el-form-item>
          <el-button
              size="large"
              type="primary"
              class="pw-100 margin-top-20"
              @click="handleBind(bindForm)"
              :loading="loading"
          >绑 定
          </el-button>
        </el-form-item>
      </el-form>
      <div class="h-80 pw-100"></div>
    </div>
  </div>
</template>
<style scoped lang="scss">
.login-container {
  background: var(--el-bg-color-page);
  min-height: 620px;
  transition: color 0.2s, background-color 0.2s;

  .login-body {
    width: 500px;
    .title {
      width: 580px;
      position: relative;
      left: 50%;
      margin-left: -290px;
    }

    .login-form {
      transition: color 0.2s, background-color 0.2s;
      background: var(--el-bg-color-overlay);
    }
  }
  .dark-btn {
    position: absolute;
    top: 10px;
    right: 20px;
  }
}
</style>